package iSOCK::Controller::Preferences;

use Sort::Naturally qw( nsort );
use Try::Tiny;

use Moose;
use namespace::autoclean;

BEGIN { extends 'Catalyst::Controller' } 

=head1 NAME

iSOCK::Controller::Preferences - Preferences Controller for iSOCK

=head1 DESCRIPTION

[enter your description here]

=head1 METHODS

=cut

sub index :Path :Args(0) {
  my ( $self, $c ) = @_;

  if ( my $user_r = $c->model ( 'App' )->user_r ( $c ) ) {
    my $parameters = $c->request->parameters;

    #
    # Specifications.
    #

    if ( $c->request->method eq 'POST' && $parameters->{form_specifications_submit} ) {
      try {
        $c->model ( 'App::UserToPreference' )->update_or_create ({ user_id => $user_r->id, preference_id => 'any_specification_event_mail', value => $parameters->{any_specification} || 'no' });
        
        if ( $parameters->{any_specification} ) {
          $c->stash->{action_succeeded} = "Any specification goes.";
        }
        else {
          $c->stash->{action_succeeded} = "Cherry-picked specifications only.";
        }
      };
      
      unless ( $parameters->{any_specification} ) {
        try {
          my $checked;
             $checked->{$_} = 1 for grep { ! m/^ ( form_ | any_ ) /x } keys %$parameters;

          my ( @successes, @failures );
          
          for my $specification_id ( nsort keys %$checked ) {
            my ( $owner_r, $writer_r, $follower_r ) = map { $c->model ( 'App::UserToSpecification' )->find ( $user_r->id, $specification_id, $_ ) } qw( owner writer follower );
            
            if ( !$owner_r && !$writer_r && !$follower_r ) {
              if ( $c->model ( 'App::UserToSpecification' )->update_or_create ({ user_id => $user_r->id, specification_id => $specification_id, authorization_id => 'follower' }) ) {
                push @successes, "Watching $specification_id specification.";
              }
              else {
                push @failures,  "Could not update $specification_id specification.";
              }
            }
          }
          
          for my $specification_r ( $c->model ( 'App::Specification' )->search ) {
            my $specification_id = $specification_r->id;
            
            next if $checked->{$specification_id};
            
            my ( $owner_r, $writer_r, $follower_r ) = map { $c->model ( 'App::UserToSpecification' )->find ( $user_r->id, $specification_id, $_ ) } qw( owner writer follower );
            
            if ( !$owner_r && !$writer_r && $follower_r ) {
              if ( $follower_r->delete ) {
                push @successes, "Ignoring $specification_id specification.";
              }
              else {
                push @failures,  "Could not update $specification_id specification.";
              }
            }
          }

          if ( @failures ) {
            $c->stash->{action_failed}    = join ( '&nbsp;&nbsp;', @failures  );
          }
          elsif ( @successes ) {
            $c->stash->{action_succeeded} = join ( '&nbsp;&nbsp;', @successes );
          }
        }
        catch {
          $c->stash ( action_failed    => "Does not compute!" );
        };
      }
    }

    my $specifications = $c->model ( 'App' )->specifications_loh ( $c );
    $c->stash ( specifications => $specifications );
    
    #
    # Datasheets.
    #

    if ( $c->request->method eq 'POST' && $parameters->{form_datasheets_submit} ) {
      try {
        $c->model ( 'App::UserToPreference' )->update_or_create ({ user_id => $user_r->id, preference_id => 'any_datasheet_event_mail', value => $parameters->{any_datasheet} || 'no' });
        
        if ( $parameters->{any_datasheet} ) {
          $c->stash->{action_succeeded} = "Any datasheet goes.";
        }
        else {
          $c->stash->{action_succeeded} = "Cherry-picked datasheets only.";
        }
      };
      
      unless ( $parameters->{any_datasheet} ) {
        try {
          my $checked;
             $checked->{$_} = 1 for grep { ! m/^ ( form_ | any_ ) /x } keys %$parameters;

          my ( @successes, @failures );
          
          for my $datasheet_id ( nsort keys %$checked ) {
            my ( $owner_r, $writer_r, $follower_r ) = map { $c->model ( 'App::UserToDatasheet' )->find ( $user_r->id, $datasheet_id, $_ ) } qw( owner writer follower );
            
            if ( !$owner_r && !$writer_r && !$follower_r ) {
              if ( $c->model ( 'App::UserToDatasheet' )->update_or_create ({ user_id => $user_r->id, datasheet_id => $datasheet_id, authorization_id => 'follower' }) ) {
                push @successes, "Watching $datasheet_id datasheet.";
              }
              else {
                push @failures,  "Could not update $datasheet_id datasheet.";
              }
            }
          }
          
          for my $datasheet_r ( $c->model ( 'App::Datasheet' )->search ) {
            my $datasheet_id = $datasheet_r->id;
            
            next if $checked->{$datasheet_id};
            
            my ( $owner_r, $writer_r, $follower_r ) = map { $c->model ( 'App::UserToDatasheet' )->find ( $user_r->id, $datasheet_id, $_ ) } qw( owner writer follower );
            
            if ( !$owner_r && !$writer_r && $follower_r ) {
              if ( $follower_r->delete ) {
                push @successes, "Ignoring $datasheet_id datasheet.";
              }
              else {
                push @failures,  "Could not update $datasheet_id datasheet.";
              }
            }
          }

          if ( @failures ) {
            $c->stash->{action_failed}    = join ( '&nbsp;&nbsp;', @failures  );
          }
          elsif ( @successes ) {
            $c->stash->{action_succeeded} = join ( '&nbsp;&nbsp;', @successes );
          }
        }
        catch {
          $c->stash ( action_failed    => "Does not compute!" );
        };
      }
    }
    
    my $datasheets = $c->model ( 'App' )->datasheets_loh ( $c );
    $c->stash ( datasheets => $datasheets );
    
    #
    # Checkboxes.
    #

    my ( $checked, $disabled, $secured );
    
    try {
      $checked ->{$_->specification_id} = 1 for $c->model ( 'App::UserToSpecification' )->search ({ user_id => $user_r->id, authorization_id => [ { '=' => 'owner' }, { '=' => 'writer' }, { '=' => 'follower' } ] });
      $disabled->{$_->specification_id} = 1 for $c->model ( 'App::UserToSpecification' )->search ({ user_id => $user_r->id, authorization_id => [ { '=' => 'owner' }, { '=' => 'writer' }                        ] });
      $checked ->{$_->datasheet_id}     = 1 for $c->model ( 'App::UserToDatasheet'     )->search ({ user_id => $user_r->id, authorization_id => [ { '=' => 'owner' }, { '=' => 'writer' }, { '=' => 'follower' } ] });
      $disabled->{$_->datasheet_id}     = 1 for $c->model ( 'App::UserToDatasheet'     )->search ({ user_id => $user_r->id, authorization_id => [ { '=' => 'owner' }, { '=' => 'writer' }                        ] });
      
      $secured->{$_}                    = 1 for grep { $c->model ( 'App::Specification' )->find ( $_ )->secure } map { $_->{id} } @$specifications;
      $secured->{$_}                    = 1 for grep { $c->model ( 'App::Datasheet'     )->find ( $_ )->secure } map { $_->{id} } @$datasheets;
    };

    $c->stash ( checked => $checked, disabled => $disabled, secured => $secured );

    if ( $c->model ( 'App::UserToPreference' )->search ({ user_id => $user_r->id, preference_id => 'any_specification_event_mail', value => 'yes' })->first ) {
      $c->stash ( any_specification_event_mail => 1 );
    }
    if ( $c->model ( 'App::UserToPreference' )->search ({ user_id => $user_r->id, preference_id => 'any_datasheet_event_mail',     value => 'yes' })->first ) {
      $c->stash ( any_datasheet_event_mail     => 1 );
    }
    
    #
    # Login.
    #
    
    if ( $c->request->method eq 'POST' && $parameters->{form_login_uri_submit} ) {
      try {
        $c->model ( 'App::UserToPreference' )->update_or_create ({ user_id => $user_r->id, preference_id => 'login_uri', value => $parameters->{login_uris} });
        
        $c->stash ( action_succeeded => "Updated login."    );
      }
      catch {
        $c->stash ( action_failed    => "Does not compute!" );
      };
    }
    
    if ( my $login_uri = $user_r->login_uri ) {
      $c->stash ( current_login_uri => $login_uri );
    }
  }
  
  $c->forward ( qw( iSOCK::Controller::Root render_view ) );
}

sub end : ActionClass('RenderView') {}

=head1 AUTHOR

Xavier Caron

=head1 LICENSE

This library is free software, you can redistribute it and/or modify
it under the same terms as Perl itself.

=cut

1;
